// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: GPL-3.0-only

package image_api_impl

import (
	"context"
	"time"

	"gitcode.com/openseaotter/so_proto_gen_go.git/image_api"
	"gitcode.com/openseaotter/so_server/config"
	"gitcode.com/openseaotter/so_server/storage"
)

func (apiImpl *ImageApiImpl) ListImage(ctx context.Context, req *image_api.ListImageRequest) (*image_api.ListImageResponse, error) {
	emptyList := []*image_api.ImageInfo{}

	cfg, err := config.ReadServerConfigFromCache()
	if err != nil {
		return nil, err
	}
	groupInfo, err := storage.ImageGroupDao.Get(ctx, req.GroupName)
	if err != nil {
		return &image_api.ListImageResponse{
			Code:      image_api.ListImageResponse_CODE_NO_GROUP,
			ErrMsg:    "镜像分组不存在",
			ImageList: emptyList,
		}, nil
	}

	if cfg.SuperToken != "" && req.AccessToken == cfg.SuperToken {
		//do nothing
	} else {
		remoteCfg, ok := cfg.GetRemote(req.RemoteId)
		if !ok {
			return &image_api.ListImageResponse{
				Code:      image_api.ListImageResponse_CODE_NO_REMOTE,
				ErrMsg:    "鉴权服务器不存在",
				ImageList: emptyList,
			}, nil
		}
		remoteMember, _, err := storage.QueryMember(ctx, remoteCfg.RemoteAddr, req.AccessToken)
		if err != nil {
			return &image_api.ListImageResponse{
				Code:      image_api.ListImageResponse_CODE_NO_PERMISSION,
				ErrMsg:    "没有权限",
				ImageList: emptyList,
			}, nil
		}
		match := false
		memberListPerm := groupInfo.PermInfo.MemberPerm[remoteMember.ProjectId]
		if memberListPerm != nil {
			for _, viewUserId := range memberListPerm.MemberUserIdForView {
				if viewUserId == remoteMember.MemberUserId {
					match = true
					break
				}
			}
		}
		if !(match || groupInfo.PermInfo.PublicGroup || remoteMember.MemberIsAdmin) {
			return &image_api.ListImageResponse{
				Code:      image_api.ListImageResponse_CODE_NO_PERMISSION,
				ErrMsg:    "没有权限",
				ImageList: emptyList,
			}, nil
		}
	}

	imageInfoList, err := storage.ImageInfoDao.List(ctx, true, req.GroupName)
	if err != nil {
		return nil, err
	}

	count := len(imageInfoList)

	start := int(req.Offset)
	end := start + int(req.Limit)
	if start >= count {
		return &image_api.ListImageResponse{
			Code:       image_api.ListImageResponse_CODE_OK,
			TotalCount: uint32(count),
			ImageList:  emptyList,
		}, nil
	}
	if end > count {
		end = count
	}

	return &image_api.ListImageResponse{
		Code:       image_api.ListImageResponse_CODE_OK,
		TotalCount: uint32(count),
		ImageList:  imageInfoList[start:end],
	}, nil
}

func (apiImpl *ImageApiImpl) ListAllImage(ctx context.Context, req *image_api.ListAllImageRequest) (*image_api.ListAllImageResponse, error) {
	emptyList := []*image_api.ImageInfo{}

	cfg, err := config.ReadServerConfigFromCache()
	if err != nil {
		return nil, err
	}

	if cfg.SuperToken != "" && req.AccessToken == cfg.SuperToken {
		//do nothing
	} else {
		remoteCfg, ok := cfg.GetRemote(req.RemoteId)
		if !ok {
			return &image_api.ListAllImageResponse{
				Code:      image_api.ListAllImageResponse_CODE_NO_REMOTE,
				ErrMsg:    "鉴权服务器不存在",
				ImageList: emptyList,
			}, nil
		}
		_, localMember, err := storage.QueryMember(ctx, remoteCfg.RemoteAddr, req.AccessToken)
		if err != nil {
			return &image_api.ListAllImageResponse{
				Code:      image_api.ListAllImageResponse_CODE_NO_PERMISSION,
				ErrMsg:    "没有权限",
				ImageList: emptyList,
			}, nil
		}

		if !localMember.Perm.ManageWatch { //和watch接口配合使用，需要manageWatch权限
			return &image_api.ListAllImageResponse{
				Code:      image_api.ListAllImageResponse_CODE_NO_PERMISSION,
				ErrMsg:    "没有权限",
				ImageList: emptyList,
			}, nil
		}
	}

	imageInfoList, err := storage.ImageInfoDao.List(ctx, false, "")
	if err != nil {
		return nil, err
	}

	return &image_api.ListAllImageResponse{
		Code:      image_api.ListAllImageResponse_CODE_OK,
		ImageList: imageInfoList,
	}, nil
}

func (apiImpl *ImageApiImpl) GetImage(ctx context.Context, req *image_api.GetImageRequest) (*image_api.GetImageResponse, error) {
	emptyInfo := &image_api.ImageInfo{}

	cfg, err := config.ReadServerConfigFromCache()
	if err != nil {
		return nil, err
	}
	groupInfo, err := storage.ImageGroupDao.Get(ctx, req.GroupName)
	if err != nil {
		return &image_api.GetImageResponse{
			Code:   image_api.GetImageResponse_CODE_NO_GROUP,
			ErrMsg: "镜像分组不存在",
			Image:  emptyInfo,
		}, nil
	}

	if cfg.SuperToken != "" && req.AccessToken == cfg.SuperToken {
		//do nothing
	} else {
		remoteCfg, ok := cfg.GetRemote(req.RemoteId)
		if !ok {
			return &image_api.GetImageResponse{
				Code:   image_api.GetImageResponse_CODE_NO_REMOTE,
				ErrMsg: "鉴权服务器不存在",
				Image:  emptyInfo,
			}, nil
		}
		remoteMember, _, err := storage.QueryMember(ctx, remoteCfg.RemoteAddr, req.AccessToken)
		if err != nil {
			return &image_api.GetImageResponse{
				Code:   image_api.GetImageResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
				Image:  emptyInfo,
			}, nil
		}
		match := false
		memberListPerm := groupInfo.PermInfo.MemberPerm[remoteMember.ProjectId]
		if memberListPerm != nil {
			for _, viewUserId := range memberListPerm.MemberUserIdForView {
				if viewUserId == remoteMember.MemberUserId {
					match = true
					break
				}
			}
		}
		if !(match || groupInfo.PermInfo.PublicGroup || remoteMember.MemberIsAdmin) {
			return &image_api.GetImageResponse{
				Code:   image_api.GetImageResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
				Image:  emptyInfo,
			}, nil
		}
	}
	exist, err := storage.ImageInfoDao.Exist(ctx, req.GroupName, req.ImageName)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &image_api.GetImageResponse{
			Code:   image_api.GetImageResponse_CODE_NO_IMAGE,
			ErrMsg: "镜像信息不存在",
			Image:  emptyInfo,
		}, nil
	}
	imageInfo, err := storage.ImageInfoDao.Get(ctx, req.GroupName, req.ImageName)
	if err != nil {
		return nil, err
	}

	return &image_api.GetImageResponse{
		Code:  image_api.GetImageResponse_CODE_OK,
		Image: imageInfo,
	}, nil
}

func (apiImpl *ImageApiImpl) RemoveImage(ctx context.Context, req *image_api.RemoveImageRequest) (*image_api.RemoveImageResponse, error) {
	cfg, err := config.ReadServerConfigFromCache()
	if err != nil {
		return nil, err
	}
	groupInfo, err := storage.ImageGroupDao.Get(ctx, req.GroupName)
	if err != nil {
		return &image_api.RemoveImageResponse{
			Code: image_api.RemoveImageResponse_CODE_OK,
		}, nil
	}
	if cfg.SuperToken != "" && req.AccessToken == cfg.SuperToken {
		//do nothing
	} else {
		remoteCfg, ok := cfg.GetRemote(req.RemoteId)
		if !ok {
			return &image_api.RemoveImageResponse{
				Code:   image_api.RemoveImageResponse_CODE_NO_REMOTE,
				ErrMsg: "鉴权服务器不存在",
			}, nil
		}
		remoteMember, _, err := storage.QueryMember(ctx, remoteCfg.RemoteAddr, req.AccessToken)
		if err != nil {
			return &image_api.RemoveImageResponse{
				Code:   image_api.RemoveImageResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
		match := false
		memberListPerm := groupInfo.PermInfo.MemberPerm[remoteMember.ProjectId]
		if memberListPerm != nil {
			for _, removeUserId := range memberListPerm.MemberUserIdForRemove {
				if removeUserId == remoteMember.MemberUserId {
					match = true
					break
				}
			}
		}
		if !match {
			return &image_api.RemoveImageResponse{
				Code:   image_api.RemoveImageResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
	}

	imageInfo, err := storage.ImageInfoDao.Get(ctx, req.GroupName, req.ImageName)
	if err != nil {
		return &image_api.RemoveImageResponse{
			Code: image_api.RemoveImageResponse_CODE_OK,
		}, nil
	}
	//检查是否存在镜像reference
	if !req.Force && imageInfo.ReferenceCount > 0 {
		return &image_api.RemoveImageResponse{
			Code:   image_api.RemoveImageResponse_CODE_HAS_REFERENCE,
			ErrMsg: "存在镜像实例",
		}, nil
	}
	err = storage.ImageReferenceDao.RemoveByImage(ctx, req.GroupName, req.ImageName)
	if err != nil {
		return nil, err
	}
	err = storage.ImageInfoDao.Remove(ctx, req.GroupName, req.ImageName)
	if err != nil {
		return nil, err
	}
	count, err := storage.ImageInfoDao.Count(ctx, req.GroupName)
	if err != nil {
		return nil, err
	}
	groupInfo.ImageInfoCount = count
	groupInfo.UpdateTime = time.Now().UnixMilli()
	err = storage.ImageGroupDao.Update(ctx, groupInfo)
	if err != nil {
		return nil, err
	}
	return &image_api.RemoveImageResponse{
		Code: image_api.RemoveImageResponse_CODE_OK,
	}, nil
}
